package com.future.ssm.controller;

import com.future.ssm.dto.NewsDTO;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.support.BindingAwareModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.InternalResourceView;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * 主页控制器
 *
 * @author shiyong
 * 2020/12/21 9:06
 */
@Controller
public class IndexController {
    @RequestMapping("/index0")
    public ModelAndView toIndex0(HttpServletRequest request) {
        // Web容器将客户端请求封装成一个HttpServletRequest对象，在控制器方法中声明形参就可以使用HttpServletRequest等
        // 原生Servlet对象。HttpServletRequest是一个接口，具体实现类是org.apache.catalina.connector.RequestFacade
        // RequestFacade是一个包装类，它有一个org.apache.catalina.connector.Request类型的属性，真正用来封装请求信息
        // 是这个Request类。ParameterMap	parameterMap、java.util.Map<java.lang.String,java.lang.String> pathParameters、
        // byte[] postData等这些属性封装了客户端请求的参数，可以通过getParameter(java.lang.String name)等方法获取请求参数
        System.out.println(request.getClass().toString());

        // java.util.HashMap attributes这个属性用来存储属性值，
        // 可以通过void setAttribute(java.lang.String name, java.lang.Object value)方法设置属性值，
        // 通过java.lang.Object	getAttribute(java.lang.String name)方法获取属性值。
        // 通过attributes可以实现Servlet向JSP传值，或JSP向JSP传值。
        // 这里在request域中存入名称为now的值，然后在jsp页面中通过EL表达式从request域中获取now的值。
        // 这里的request对象和跳转后的JSP页面中的内置request对象是同一个对象。
        request.setAttribute("now", LocalDateTime.now());

        request.getServletContext();

        return new ModelAndView("index");
    }

    @RequestMapping("/index1")
    public ModelAndView toIndex1() {
        // ModelAndView这个类封装了模型信息和视图信息，ModelMap model封装模型信息，Object view封装了视图信息。
        // 通过ModelAndView对象将模型信息和视图信息返回给DispatcherServlet进处理。
        ModelAndView modelAndView = new ModelAndView();

        // ModelAndView的addObject将数据添加到模型中，实际调用的是ModelMap的addAttribute方法
        modelAndView.addObject("now", LocalDateTime.now());
        modelAndView.setViewName("index");

        return modelAndView;
    }

    @RequestMapping("/index2")
    public ModelAndView toIndex2(ModelMap modelMap) {
        // 打印ModelMap具体对象的类信息
        // 输出的类信息为org.springframework.validation.support.BindingAwareModelMap
        // BindingAwareModelMap继承了ExtendedModelMap，ExtendedModelMap继承了ModelMap实现了Model接口
        // 所以声明形参时可以用ModelMap modelMap、Model model或Map<String, Object> map，
        // 最终Spring传入的对象都是BindingAwareModelMap类的实例
        System.out.println(modelMap.getClass());

        // 将数据添加到模型信息中，视图渲染的时候会将模型中的数据存入request对象的属性中，这和通过request.setAttribute添加数据
        // 是一样的效果
        modelMap.addAttribute("now", LocalDateTime.now());

        return new ModelAndView("index");
    }

    @RequestMapping("/index3")
    public ModelAndView toIndex3(Model model) {
        // 打印的对象类信息为org.springframework.validation.support.BindingAwareModelMap
        System.out.println(model.getClass());

        // 将数据添加到模型信息中
        model.addAttribute("now", LocalDateTime.now());

        return new ModelAndView("index");
    }

    @RequestMapping("/index4")
    public ModelAndView toIndex4(Map<String, Object> map) {
        // 打印的对象类信息为org.springframework.validation.support.BindingAwareModelMap
        System.out.println(map.getClass());

        // 将数据添加到模型信息中
        map.put("now", LocalDateTime.now());

        return new ModelAndView("index");
    }

    @RequestMapping("/index5")
    public ModelAndView toIndex5() {
        // 手动创建的BindingAwareModelMap对象无法将数据传递到JSP，因为Spring没有持有该对象的引用，无法将里面的值设置到request对象中
        // 需要将BindingAwareModelMap对象手动设置到ModelAndView对象中，才可以将数据传入到JSP页面
        ModelMap modelMap = new BindingAwareModelMap();
        // 打印的对象类信息为org.springframework.validation.support.BindingAwareModelMap
        System.out.println(modelMap.getClass());

        // 将数据添加到模型信息中
        modelMap.addAttribute("now", LocalDateTime.now());

        return new ModelAndView("index");
    }

    @RequestMapping("/index6")
    public String toIndex6(Model model) {
        // 将数据添加到模型信息中
        model.addAttribute("now", LocalDateTime.now());

        // 这里返回的是视图名称，Spring MVC会使用ModelAndView(String viewName)这个构造方法将其封装成一个ModelAndView对象
        // 所以这里和返回new ModelAndView("index")是一样的效果
        // 这是日常开发中常用的方式
        return "index";
    }

    @RequestMapping("/index7")
    public InternalResourceView toIndex7(Model model) {
        // 将数据添加到模型信息中
        model.addAttribute("now", LocalDateTime.now());

        // 返回视图对象，通过ModelAndView(View view)构造方法封装成一个ModelAndView对象
        return new InternalResourceView("/WEB-INF/page/index.jsp");
    }

    @ResponseBody
    @RequestMapping("/getMessage")
    public String getMessage() {
        return "hello，欢迎您！";
    }

}
